//
//  RFATree.m
//  RFA Manager
//
//  Created by Torsten Kammer on 23.02.08.
//  Copyright 2008 Ferroequinologist.de. All rights reserved.
//

#import "RFATreeNode.h"
#import "RFAArchive.h"

@interface RFATreeNode ()

- (id)initAsFolderWithName:(NSString *)name parent:(RFATreeNode *)node;
- (id)initWithArchiveEntry:(RFAArchiveEntry *)entry;
- (void)addArchiveEntry:(RFAArchiveEntry *)anEntry atPath:(NSArray *)pathComponents;
- (RFATreeNode *)childWithPathArray:(NSArray *)pathArray createIfNeeded:(BOOL)create;

@end

@implementation RFATreeNode

- (id)copyWithZone:(NSZone *)zone
{
    RFATreeNode *result = [[self class] allocWithZone:zone];
    result->isLeaf = isLeaf;
    result->path = path;
    result->entry = entry;
    result->children = [children mutableCopyWithZone:zone];
    return result;
}

- (id)initAsRoot
{
    if (![super init]) return nil;
    
    isLeaf = NO;
    path = @"/";
    entry = nil;
    children = [NSMutableDictionary dictionary];
    
    return self;
}

- (id)initAsFolderWithName:(NSString *)aName parent:(RFATreeNode *)above;
{
    if (![super init]) return nil;
    
    isLeaf = NO;
    path = [[above.path stringByAppendingPathComponent:aName] stringByAppendingString:@"/"];
    entry = nil;
    children = [NSMutableDictionary dictionary];
    
    return self;
}

- (id)initWithArchiveEntry:(RFAArchiveEntry *)anEntry;
{
    if (![super init]) return nil;
    
    isLeaf = YES;
    path = anEntry.path;
    entry = anEntry;
    children = nil;
    
    return self;
}

- (void)addArchiveEntry:(RFAArchiveEntry *)anEntry;
{
    if (isLeaf) return;
    [self addArchiveEntry:anEntry atPath:anEntry.path.pathComponents];
}
- (void)addArchiveEntry:(RFAArchiveEntry *)anEntry atPath:(NSArray *)pathComponents;
{
    if (isLeaf) return;
    if ([pathComponents count] == 1)
    {
        RFATreeNode *newDataNode = [[RFATreeNode alloc] initWithArchiveEntry:anEntry];
        [children setObject:newDataNode forKey:anEntry.path];
    }
    else
    {
        RFATreeNode *folder = [self childWithName:[pathComponents objectAtIndex:0] createIfNeeded:YES];
        [folder addArchiveEntry:anEntry atPath:[pathComponents subarrayWithRange:NSMakeRange(1, pathComponents.count - 1)]];
    }
}

- (RFATreeNode *)childWithName:(NSString *)aName createIfNeeded:(BOOL)create;
{
    if (!children) return nil;
    
    RFATreeNode *result = [children objectForKey:aName];
    if (!result && create)
    {
        result = [[RFATreeNode alloc] initAsFolderWithName:aName parent:self];
        [children setObject:result forKey:aName];
    }
    return result;
}

- (RFATreeNode *)childWithPath:(NSString *)name createIfNeeded:(BOOL)create;
{
    return [self childWithPathArray:name.pathComponents createIfNeeded:create];
}

- (RFATreeNode *)childWithPathArray:(NSArray *)pathArray createIfNeeded:(BOOL)create;
{
    if ([pathArray count] == 1) return self;
    RFATreeNode *directChild = [self childWithName:[pathArray objectAtIndex:0] createIfNeeded:create];
    if (!directChild) return nil;
    return [directChild childWithPathArray:[pathArray subarrayWithRange:NSMakeRange(1, pathArray.count - 1)] createIfNeeded:create];
}

@synthesize isLeaf;
@dynamic children;
- (NSArray *)children
{
    return [children allValues];
}

@synthesize path;
@synthesize entry;

@dynamic size;
- (NSUInteger)size
{
	 if (isLeaf) return entry.data.length;
	 else return [[self valueForKeyPath:@"children.@sum.size"] unsignedIntegerValue];
}

@dynamic data;
- (NSData *)data
{
	return self.entry.data;
}

@dynamic contents;
- (NSString *)contents
{
	return self.entry.contents;
}

@dynamic image;
- (NSImage *)image
{
	return self.entry.image;
}

@end
